home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!nic.MR.NET!hal!cwjcc!tut.cis.ohio-state.edu!mailrus!ulowell!page
- From: page@swan.ulowell.edu (Bob Page)
- Newsgroups: comp.sources.amiga
- Subject: v02i015: dres - an object-oriented resource library (docs)
- Message-ID: <9820@swan.ulowell.edu>
- Date: 25 Oct 88 00:08:17 GMT
- Organization: University of Lowell, Computer Science Dept.
- Lines: 1588
- Approved: page@swan.ulowell.edu
-
- Submitted-by: dillon@cory.berkeley.edu (Matt Dillon)
- Posting-number: Volume 2, Issue 15
- Archive-name: util/dres.docs
-
- # This is a shell archive. Remove anything before this line
- # then unpack it by saving it in a file and typing "sh file"
- # (Files unpacked will be owned by you and have default permissions).
- # This archive contains the following files:
- # ipc.doc
- # lists.doc
- # memory.doc
- # misc.doc
- # qints.doc
- # res.doc
- # runlib.doc
- # timedate.doc
- #
- if `test ! -s ipc.doc`
- then
- echo "writing ipc.doc"
- cat > ipc.doc << '\Rogue\Monster\'
-
- IPC.DOC (DRES.LIBRARY)
-
- Matthew Dillon
- 25 September 1988
-
-
- Special note. I've tried my best, but this document is somewhat
- lacking in the exact mechanics and implementation of IPC. Please
- refer to the source module to resolve such questions.
-
- The IPC section of the DRES.LIBRARY pertains to the sending of commands
- and retrieval of results between arbitrary processes without conflict.
- Processes which use IPC come in three flavors:
-
- (1) A process which is able to accept and process IPC commands
- (2) A process which might send IPC commands to other processes
- (3) A process which does both.
-
- The IPC mechanism implemented by this library is inherently asychronous
- in nature (messages and ports), but also provides a synchronous call
- specially tailored for cases (2) and (3). Doing IPC commands synchronously
- has certain advantages, the greatest of which is that the implementation by
- application software is greatly simplified. The synchronous call gets
- around possible deadlocks in case (3) by interrupting itself and calling a
- handler if incomming messages occur while it is waiting for the sent
- message to complete.
-
- The greatest feature of this IPC mechanism is a great flexibility in
- who allocates and deallocates the message buffers. Both the source and
- destination processes have a wide range of options concerning message
- buffers. Unless otherwise specified, an allocated copy of the message
- buffer is automatically made and used which allows the send or reply message
- buffer used by the process to be immediately discarded. Additionaly, a
- destination IPCPort can be flagged to force incomming messages to be
- allocated no matter what the sender requests.
-
- NOTE: The term 'allocation of messages' inherently means that if the
- message is allocated, the user of the message can munge it however he likes
- (exception: IF_GLOBAL messages that are propogated through all IPC ports).
- Allocated messages are automatically FreeMem()d by the IPC subsystem or
- by the receiver. Also, WHEN DUPLICATION OF MESSAGES OCCUR, THE ALLOCATED
- MEMORY IS OF THE SAME TYPE AS THE ORIGINAL BUFFER.
-
- NOTE: Do not get confused by the many different ways messages buffers
- can be allocated. A message buffer will never be allocated-duplicate more
- than once. For example, if the source specifies that it is passing an
- allocated buffer, the further duplication is done by the IPC subsystem.
-
- -The sender can allocate the message buffer himself and pass that,
- pass a temporary buffer which the IPC subsystem duplicates, or pass
- a static buffer to the destination without the overhead of allocation
- and duplication.
-
- -The receiver of a particular message can determine whether that message
- was allocated and FreeMem() it himself, can allow the IPC subsystem
- to free allocated messages, and can even force all incomming messages
- on his IPC port to be allocated no matter what the sender specifies.
- Forcing the IPC subsystem to allocate otherwise static messages is
- a very useful ability to have. For instance, the parser employed by
- the receiver of a message might destroy or modify the message buffer
- during parser, while the original sender of the message might have
- used a static string or otherwise expected the buffer not to be
- screwed up. By the receiver being able to specify that he WANTS the
- buffer to be an allocated duplicate because he intends to modify it
- without permission is a good thing. Even though the sender passes
- a static buffer to the IPC subsystem, that subsystem will allocate
- and duplicate it for the receiver.
-
- -In his reply to the sender, the receiver has the same sort of control
- as sender in terms of how the reply message buffer is allocated. After
- getting the reply back, the original sender can determine whether the
- reply buffer was allocated and FreeMem() it himself, or allow the IPC
- subsystem to free it when he is through with the reply.
-
- -Finally, the receiver of the original message can even free his own
- reply buffer when the original sender is through with it!
-
- So in general, one can use either the IPC subsystem's automatic buffer
- copying feature (the default), use no buffer copying at all, or use one's
- own scheme.
-
- MOST OF THESE ALLOCATION FEATURES ARE IMPLEMENTED THROUGH FLAGS. READ
- THE DOCS BELOW ON OPENIPC() and SENDIPC().
-
-
- APPLICATION NAME DOMAINS
-
- An application for cases (1) or (3) must create a receiver port for
- IPC messages with the OpenIPC() call. OpenIPC() takes a name and flags
- argument. The Flags argument is discussed in OpenIPC() below. You do
- not need a port to send messages, only to receive them.
-
- The name of the port determines the type of messages it will receive.
- The format is: <application_name>.<domain> , for example: "dmouse.CMD"
- Currently, only the .CMD domain has a defined standard. It does not matter
- whether multiple copies of the application are running, they can share the
- same port name. You could have, say, two invocations of your favorite
- editor each with five active projects. Support for this is discussed in
- the ReplyIPC() call below.
-
- While this port exists, other tasks may send IPC messages to it. You
- must extract the messages (GetMsg()), process it, and then ReplyIPC() the
- message to return it to the original sender.
-
- The CloseIPC() call will shutdown an IPC port that you had previously
- openning and return any pending messages by trying to pass them to the
- next application of the same name (if none, an error is eventually returned
- to the sender).
-
- .CMD ports
-
- Messages sent over .CMD ports are formatted as null-terminated
- ascii-text. The send buffer (msg->TBuf) is formatted as follows:
-
- project\0command\0 (\0 = NUL = ascii 0)
-
- The \0 MUST be included as part of the buffer and buffer length. The
- project name allows the application to identify which of its possibly
- multiple projects is to be affected by the command. a NULL project name
- (\0command\0) is allowed and refers to the 'active' project in the
- application. The project name is ignored by applications which do not
- support the notion of projects. The format of the command depends on the
- application, but must be in ascii and terminate with a \0 (ascii 0).
-
- The logical extension for the specification of multiple project names
- is to allow comma delimited names and wildcards (* and ?). For example,
- "*\0command\0" would refer to all projects, "a.c,b.c\0command\0" would
- refer to two specific projects. This might not be supported by all
- applications.
-
- The format of the reply buffer depends on the success of the operation.
- If the command was successful, the reply buffer will either be NULL or
- contain some ascii/text response ending in \0. If the command was not
- successful, IF_ERROR will be set in msg->RFlags and the reply buffer will
- be either NULL or contain some ascii/text error message ending in \0.
- The msg->Error integer error code will be non-zero if IF_ERROR was set,
- possibly non-zero if IF_ERROR was not set to indicate a warning (IF_ERROR
- always means Total-Failure). If msg->Error is not set by the application
- which returns the error condition, it will be set by the IPC subsystem.
-
-
-
- ParseCmd ParseCmd
-
- argc = ParseCmd(buf, &argv, varget, varfree, &error, NULL);
- int argc;
- char **argv; (note, address passed)
- char *((*varget)());
- void (*varfree)();
- long error; (note, address passed)
-
- (note: Last NULL argument (0L) is required for future compatibility).
-
- THIS COMMAND CAN EASILY BE USED WITH NON-IPC RELATED ROUTINES!
-
- Do DME-type parsing on a string buffer. The buffer is terminated with
- a \0 but may contain a \n at the end (which is ignored) to be compatible
- with fgets() as well as gets(). NOTE that if the string is terminated
- with a \<LF><NUL> i.e. "\\n\0", the backslash will override the standard
- ignorance of the \n and parse it into the result.
-
- DME-type parsing delimites fields by spaces except those enclosed in
- matching parenthesis. Multiple levels of parenthesis is tracked and
- the OUTERMOST SET REMOVED. Other special characters include shift-6
- (^), backslash (\), and dollar ($):
-
- form examples function
-
- ^<char> ^c ^d ^L embed a control character, case is ignored
- you may not embed ^@ (0)
-
- \<char> \\ \( \^ override the meaning of the next character,
- allows embedding special characters.
-
- $(varname) inline string variable, var name can be
- anything except ')'.
-
- $varname inline string variable, var name
- restricted to alphanumeric and '_'.
-
- Example: "echo (this (is a) test) $file/x a mess ^g \(hi! \)ug\\"
- Result: argv[0] = "echo"
- argv[1] = "this (is a) test"
- argv[2] = "dnet:foo/x" (assumes $file == 'dnet:foo')
- argv[3] = "a"
- argv[4] = "mess"
- argv[5] = "<CONTROL-G>" (i.e. ascii code 7)
- argv[6] = "(hi!"
- argv[7] = ")ug\"
- argv[8] = NULL
-
- Note: offset -1 of each argument contains a status byte. Currently,
- bit 0 is defined to indicate whether the argument was paren'd or not.
- This cannot otherwise be told as the highest level of parenthesis are
- stripped. (argv[0][-1] & 1) == 0, (argv[1][-1] & 1) == 1.
-
- --------
-
- buf -\0 or \n\0 terminated buffer holding the command to parse.
- The buffer is not modified and may be discarded after the
- call returns.
-
- &argv -address of a variable which will be initialized to point
- to an allocated array of pointers to strings exactly the
- way the main() argv works.
-
- varget -Pointer to a subroutine which when given a \0 terminated
- variable name will return a \0 terminated string or NULL
- if that variable does not exist.
-
- varget(varname)
- char *varname;
-
- This argument may be NULL indicating string variables are
- not supported. The routine may return non-allocated
- strings (i.e. static storage or string constants) in which
- case there is no need for a varfree() function.
-
- varfree -Pointer to a subroutine which when given the string
- pointer returned by varget() will free it. This call
- is made immediately after varget() is called and returns
- nothing. You may pass NULL for this argument if no free
- function exists (varget was NULL or returned static
- strings).
-
- &error -You must supply a pointer to a longword which will be
- returned holding the error, if any, and the index where
- the error occured, if any. The index is stored in the
- lower 16 bits and the error # stored in the upper 16 bits:
-
- 1 << 16 = NO MEMORY
- 2 << 16 = STRING VARIABLE NOT FOUND (varget() returned
- NULL), the lower 16 bits contain the index into
- buf.
-
- NULL -This argument is reserved for future expansion and must
- be NULL (0L).
-
- NOTE: The returned arg list may be munged however you wish, including
- the pointers themselves, just as long as you pass the original
- argv pointer (i.e. the entries may be munged) to FreeParseCmd().
-
- 0 is always returned on error, and error will be set properly.
- Otherwise, argc is returned and error will hold 0.
-
- The original buffer is not modified in any way.
-
- NOTE: Since the outer set of parenthesis () are stripped, offset -1
- of each arguments provides information as to whether the
- argument was quoted or not. If bit 0 is set, the argument
- was quoted, I.E.: (a) b c
- (av[0][-1] & 1) = 1 av[0] = "a"
- (av[1][-1] & 1) = 0 av[1] = "b"
- (av[2][-1] & 1) = 0 av[2] = "c"
-
-
- FreeParseCmd FreeParseCmd
-
- (void) FreeParseCmd(argv)
-
- This routine frees the storage referenced by the argv... the argv array
- and the original strings are all freed. It is ok if Individual entries
- in the argv array are munged.
-
-
- OpenIPC OpenIPC
-
- port = OpenIPC(name, flags)
- PORT *port;
- char *name;
- long flags;
-
- Create an IPC port of the specified name suitable for receiving IPC
- commands on. If the port could not be created due to lack of memory,
- NULL is returned, else an EXEC port is returned. The port is setup
- as PA_SIGNAL and takes up a signal bit in your signal set. If the
- application does not wish a signal-port, it may FreeSignal() the
- signal and change the flags to something other than PA_SIGNAL.
-
- Due to the fact that the signal was allocated for the calling task,
- the port is normally usable only from the calling task. One can
- change the ownership and port characterstics but always remember that
- CloseIPC() can only be called from the owning task.
-
- IF_ALLOC If IF_ALLOC is specified, *ALL* incomming message buffers
- will be forced to be allocated even if the sender of the
- message specifies IF_NOCOPY. I.E. you, as the receiver of
- IPC messages on this port can specify this flag to guarentee
- the msg->TBuf is allocated and thus modify the contents
- of the buffer itself without confusing the original sender
- (who may have specified a static string)
-
- Note: However, if this message is to be passed on via
- IF_GLOBAL or IF_NOTFND, you probably do not want to munge
- the buffer.
-
- IF_GLOBAL If IF_GLOBAL is specified, this port will accept global
- messages. Global messages are always of the .CMD form
- though the sender could easily put stuff beyond the second
- \0 in the message buffer destined for specialized routines.
-
- If not specified, IF_GLOBAL messages will NEVER propogate
- through this port.
-
-
- CloseIPC CloseIPC
-
- (void) CloseIPC(port)
- PORT *port;
-
- Delete an IPC port previously obtained by OpenIPC(). The owning task
- must make this call since it will FreeSignal() the allocated signal.
- Note that if the port flags are set to something other than PA_SIGNAL,
- no attempt will be made to free the possibly non-existant signal bit.
-
- This call will pass any pending messages on to the next application
- of the same name, and if no other exists, will return the messages
- with an error. Pending messages with IF_GLOBAL set continue their
- journey through the IPC ports flagged to accept IF_GLOBAL messages.
-
-
- SendIPC SendIPC
-
- msg = SendIPC(appname, buf, len, flags)
- IPCMSG *msg;
- char *appname;
- APTR buf;
- long len, flags;
-
- This routine starts an asynchronous IPC request. It allocates and
- initializes an IPCMSG and reply port and sends the message to the
- destination application (appname). The IPCMSG is returned and it's
- msg->RFlags holds the IF_ALLOCMSG internal flag to cause the IPCMSG
- and replyport to be deallocated when you are through with the reply.
- NOTE! The returned IPCMSG has already been sent to the destination
- and is not owned by you. The idea is to then CheckMsg() and/or
- WaitMsg() on it. The ANode filed of the IPCMSG, however, *IS* owned
- by you and you may use it however you wish.
-
- The buffer and buffer length you pass SendIPC() is used to allocate
- a copy of the buffer (which is deallocated automatically when the
- destination ReplyIPC()s). This means that you can discard/reuse your
- buffer as soon as the call returns. However, if you specify the
- IF_NOCOPY flag SendIPC() will use your buffer pointer and you must
- be sure not to modify its contents until the message is returned to you.
-
- If you specify IF_ALLOC it is assumed your buffer pointer and length
- were AllocMem()d and the system will FreeMem() them when the destination
- is through processing your message and calls ReplyIPC().
-
- ** See SendIPC2() for info on how to handle the message when it comes
- back.
-
- * If the 'name' is NULL, the first application in the application
- list is called. This is usually used in conjunction with IF_GLOBAL
- to indicate that the message should propogate to all IPC ports in the
- system.
-
- SendIPC2 SendIPC2
-
- msg = SendIPC2(name, msg)
-
- This routine is called by SendIPC(). This assumes you already have an
- IPC message structure that you wish to use. The msg argument is
- returned. The reply fields, including msg->Error and msg->Confirm,
- are zerod.
-
- The IPCMSG must be initialized as follows:
-
- msg->Msg.mn_ReplyPort -must hold reply port for the message
- msg->Msg.mn_Length -must hold length of IPCMSG structure ONLY
- if you had specified the IF_ALLOCMSG in
- msg->TFlags
- msg->Msg.TBuf -holds the buffer pointer to the message
- or NULL
- msg->Msg.TLen -holds the length of the message
- msg->Msg.TFlags -holds flags associated with the message:
- IF_ALLOC * automatic deallocation on reply. This flag
- is set automatically if you do not specify
- IF_NOCOPY. If NEITHER IF_NOCOPY or IF_ALLOC
- are specified, the IPC subsystem will
- allocate a duplicate of your buffer, place
- it in TBuf, and set this flag for you.
- IF_GLOBAL * force propogate to all applications in
- the system before returning to the sender.
- IF_NOCOPY * force IPC system to use the buffer you
- placed in TBuf. Otherwise, the IPC system
- will allocate and copy your buffer into
- its own and place that in TBuf.
-
- IF_ALLOCMSG * IPC system will deallocate the IPCMSG
- itself when FreeIPC() is called. This
- flag is set automatically when the IPC
- system has allocate the IPCMSG in the
- first place.
-
- WARNING! Upon return, msg->TBuf will not necessarily point to your
- buffer, even if you specified IF_NOCOPY or IF_ALLOC.
-
- Handling the message when it comes back
-
- After you make the call, you must wait for the message to complete
- via WaitMsg and/or CheckMsg(). Note that WaitMsg() will remove the
- message from its reply port. If you do not use WaitMsg(), you must
- remember to remove the message before continuing.
-
- Then, process the reply (msg->RBuf, msg->RLen, and msg->RFlags).
- The msg->RBuf IS ALLOWED TO BE NULL. msg->RFlags will indicate
- any errors:
-
- IF_ERROR|IF_NOTFND|IF_NOAPP: no application of that name exists
-
- IF_ERROR|IF_NOTFND : application exists, but the requested
- project does not exist. OR the
- command does not exist for this
- application.
-
- IF_ERROR : The application exists and can handle
- the project & command, but an error
- occured during interpretation of the
- command.
-
- IF_ALLOC : The reply buffer was allocated. You
- have the option of FreeMem()ing it
- yourself or allowing the system to
- do so. If you do it, you must set
- RBuf = NULL.
-
- NOTE: msg->Error does not need to be set by the receiver. If
- msg->Error is 0 and IF_ERROR is set, msg->Error will be set to
- 20 by the IPC subsystem.
-
- NOTE: In the case of IF_ERROR, the reply buffer might still be
- non-NULL and contain an error message.
-
- When through dealing with the reply, you MUST call FreeIPC(msg). This
- routine will deallocate the reply buffer if msg->RFlags had IF_ALLOC
- set by the destination and also free the message it self if msg->TFlags
- contained IF_ALLOCMSG set by SendIPC() or the user before a SendIPC2().
-
- Additionaly, if msg->Confirm was set by the destination, this function
- vector will be called with the message pointer as an argument to allow
- the destination to deallocate its reply. NOTE!!! If the message has
- IF_GLOBAL set in msg->TFlags, msg->Confirm should NOT be touched by
- receiving applications.
-
-
- DoIPC2 DoIPC2
-
- (void) DoIPC2(name, msg, collfunc, collport)
- long flags
- char *name;
- IPCMSG *msg;
- void (*collfunc)();
- PORT *collport;
-
- This is the hall mark of the IPC library and allows one to send
- SEMI-SYNCHRONOUS messages while still retaining the ability to
- process incomming messages on your own IPC port (case #3). The IPC
- message msg must be setup as in SendIPC2(). The collision function
- and collision port may be NULL if you wish.
-
- This command sends the message and then waits for the reply. If while
- waiting for the reply a message comes in on the collision port (usually
- your IPC port), the collision vector will be called with the collision
- port as an argument, allowing you to process incomming messages while
- waiting for one you sent. By properly designing your software, you
- can allow multiply stacked DoIPC2() calls.
-
- When the message finally comes back, this call returns. The application
- must still deal with its reply buffer and call IPCFree() when through.
-
- NOTE: The collision function is called as a subroutine of this routine
- and thus if it is a general command-handling routine remember that
- your command interpreter might have to be synchronously reentrant.
- DoIPC2() is certainly reentrant. A4 and A5 are not screwed up by
- DoIPC2() so you do not have to reload your data segment base register
- from the collision vector routine if using the small data model.
- (Compatible with both Aztec and Lattice C).
-
-
- ReplyIPC ReplyIPC
-
- (void) ReplyIPC(msg, buf, len, flags)
- IPCMSG *msg;
- APTR buf; (may be NULL & len would then be 0)
- long len;
- long flags;
-
- You must reply to all IPC messages you receive on your IPC port by
- calling ReplyIPC(). ReplyIPC() works almost exactly like IPCSend(),
- but deals with the RBuf, RFlags, and RLen fields of the IPC structure.
- Normally, the IPC system will allocate a duplicate of your reply buffer
- and stick that in msg->RBuf which allows you to throw away your buffer
- after calling ReplyIPC(). Various flags override this feature:
-
- IF_ALLOC - The buffer is automatically deallocated when the
- source calls FreeIPC(). If this flag exists the
- IPC system will not allocate a duplicate buffer.
-
- IF_NOCOPY - The IPC system will not allocate a duplicate buffer.
-
- Normally, (1) neither of these flags is specified, or (2) IF_ALLOC
- is specified. Specifying IF_ALLOC alone means that the IPC system
- assumes you have AllocMem()d the buffer yourself and want it
- automatically freed when the source (original sender) calls
- FreeIPC().
-
- Specifying both IF_ALLOC and IF_NOCOPY is equivalent to specifying
- just IF_ALLOC. Specifying just IF_NOCOPY means that the IPC system
- will use your buffer pointer and will NOT attempt to deallocate it.
- In this case, you are responsible for keeping the buffer intact
- until the source calls FreeIPC(). This is possible through the
- use of the msg->Confirm vector. ** you cannot use msg->Confirm
- for IF_GLOBAL packets! Because there is only one vector entry and
- possibly multiple users of the message.
-
- NOTE: The buffer pointer placed in msg->RBuf will either be yours
- or the allocated duplicate. msg->RBuf will be set to NULL when (if)
- the system deallocates it.
-
- If you specify IF_NOTFND, your buffer and length are completely
- ignored and the message is passed on to the next application program
- with the same name. IF THE ORIGINATOR SPECIFIED IF_GLOBAL WHEN HE
- SENT THE MESSAGE, AND YOU DID NOT SPECIFY IF_NOTFND, the message
- will be passed on to the next application anyway and your reply will be
- passed on along with it. In the same way, if you were not the first
- application to get this message (it was passed to you), the
- msg->RBuf/RLen/RFlags fields may already have something in them. If
- your reply buffer pointer is not the same address as the one already in
- msg->RBuf and msg->RFlags held IF_ALLOC, the old buffer in msg->RBuf
- will be deallocated before processing continues with your ReplyIPC().
-
- ** Warning, msg->RBuf will be replaced in the same manner msg->TBuf
- is by an allocated duplicate unless you specify otherwise.
-
-
- FreeIPC FreeIPC
-
- (void) FreeIPC(msg)
- IPCMSG *msg;
-
- This routine must be called when the original sender of an IPC message
- has sent the message, waited for the reply, removed the message from
- the reply port, and processed the reply buffer. This serves to free
- the message and any associated buffers as specified below:
-
- If msg->RFlags has IF_ALLOC set the reply buffer is immediately
- deallocated and msg->RBuf set to NULL.
-
- If msg->Confirm is non-NULL the vector will be called with the IPCMSG
- as an argument.
-
- If msg->TFlags holds IF_ALLOCMSG, the msg will be FreeMem()d with the
- length msg->Msg.mn_Length. IF_ALLOCMSG is not usually set by the
- user... it is set by SendIPC() which allocates a message/replyport
- and wants both to be deallocated on completion.
-
-
-
-
- \Rogue\Monster\
- else
- echo "will not over write ipc.doc"
- fi
- if [ `wc -c ipc.doc | awk '{printf $1}'` -ne 24710 ]
- then
- echo `wc -c ipc.doc | awk '{print "Got " $1 ", Expected " 24710}'`
- fi
- if `test ! -s lists.doc`
- then
- echo "writing lists.doc"
- cat > lists.doc << '\Rogue\Monster\'
-
- LISTS.DOC
-
- These are general list handling routines that should have been provided
- in EXEC. In addition to basic additions, I provide support for structures
- whos Nodes are not at the base of the structure. These are the infamous
- 'sptr's below. Such routines take a pointer to the structure, add an
- offset to it to get to the Node, do the specified operation, then subtract
- the offset to return to the 'sptr's actual base. In otherwords, it allows
- you to deal with such structures without having to do these hacks in your
- source.
-
- GetHead GetHead
- GetSucc GetSucc
-
- node = GetHead(list)
- node = GetSucc(node) (physically the same routine as GetHead()).
-
- This routine returns the successor of a node in the list. If a list is
- specified, the first node in the list is returned. NULL is returned if
- the list is empty or one has reached the end of the list.
-
- GetTail GetTail
-
- node = GetTail(list)
-
- This routine returns the last node in the list, or NULL if the list
- is empty.
-
- GetPred GetPred
-
- node = GetPred(node)
-
- This routine returns the previous node from the given node, or NULL
- if we are at the head of the list.
-
- GetHeadOff GetHeadOff
-
- sptr = GetHeadOff(list, offset)
-
- This routine retrieves the first node in the list and subtracts the
- specified offset to get to the base of the structure (where 'offset'
- is the offset into the structure where the Node has been placed rather
- than placing it as the first object in the structure).
-
- NULL is returned is the list is empty. NOTE! Unlike GetHead(), only
- a valid list pointer may be specified here.
-
- GetTailOff GetTailOff
-
- sptr = GetTailOff(list, offset)
-
- This routine works the same as GetHeadOff() but works on the last
- node in the list.
-
- GetSuccOff GetSuccOff
-
- sptr = GetSuccOff(sptr, offset)
-
- Given a structure pointer where the Node is offset from the structure
- base, add the offset to the pointer, determine the successor if any,
- then subtract the offset from the successor to get back to the
- structure base for the successor.
-
- NULL is returned if there is no successor.
-
- GetPredOff GetPredOff
-
- sptr = GetPredOff(sptr, offset)
-
- This routine works the same as GetSuccOff() but works on the previous
- node rather than the next. NULL is returned if we are at the head
- of the list;
-
- EnqueueLong EnqueueLong
-
- (void) EnqueueLong(list, startnode, node, valoff)
-
- This routine queues a node into a list beginning its search at the
- startnode (first element if startnode == NULL). The list is assumed
- to be sorted by the longword valoff from the node structure. I.E.
- If you had a graphic structure with a Node at its base and where
- coordinates were stored in longwords, you insert nodes sorted by
- one of the coordinates into a list.
-
- valoff is the offset from the node base where the longword value
- the list is sorted by exists.
-
- EnqueueOffLong EnqueueOffLong
-
- (void) EnqueueOffLong(list, startnode, sptr, off, valoff)
-
- This works just like EnqueueLong() but an extra parameter, 'off', is
- provided to inform the routine where in the structure the Node is.
- Does that make sense?
-
- SearchFwdNode SearchFwdNode
-
- retval = SearchFwdNode(node, function, arg)
- MINNODE *node;
- long (*function)();
- long arg;
-
- This routine searches a list in the forward direction beginning at
- the specified node, calling the function vector for every node. The
- function is called C-fashion (A4 and A5 are intact to support the
- small code model and D2/D3 may be destroyed in addition to standard
- scratch variables to support Aztec C). The function is given two
- arguments: the node, and the arg passed to SearchFwdNode():
-
- (*function)(current_srch_node, arg)
-
- The search is terminated if the function vector returns a non-zero
- value. If the search reaches the end of the list, NULL is returned.
- NOTE: you may pass a NULL as the node to SearchFwdNode() which results
- in a NULL being immediately returned.
-
- SearchRvsNode SearchRvsNode
-
- retval = SearchFwdNode(node, function, arg)
-
- This function works exactly the same as SearchFwdNode() but works
- in reverse begining at the specified node.
-
- SearchFwdList SearchFwdList
-
- retval = SearchFwdList(list, function, arg)
-
- This function works exactly the same as SearchFwdNode() but you give
- it a pointer to a list rather than to a node.
-
- A valid list pointer must be specified, but the list may be empty.
-
- SearchRvsList SearchRvsList
-
- retval = SearchRvsList(list, function, arg)
-
- This function works exactly the same as SearchRvsNode() but you give
- it a pointer to a list rather than to a node.
-
- A valid list pointer must be specified, but the list may be empty.
-
- SearchFwdNodeOff SearchFwdNodeOff
- SearchRvsNodeOff SearchRvsNodeOff
- SearchFwdListOff SearchFwdListOff
- SearchRvsListOff SearchRvsListOff
-
- rval = SearchFwdNodeOff(sptr, function, off, arg)
- rval = SearchRvsNodeOff(sptr, function, off, arg)
- rval = SearchFwdListOff(list, function, off, arg)
- rval = SearchRvsListOff(list, function, off, arg)
-
- These routines work like those shown above, but an additional
- argument, an offset, is supplied. This is the offset into the
- structure pointer where the Node structure is embedded. In otherwords,
- the other routines were simply special cases of this one with off == 0.
-
- Note that for *NodeOff() routines a pointer to a structure containing
- the Node structure in it somewhere is supplied, whereas in the
- *ListOff() routines a pointer to the list base is given (this hasn't
- changed).
-
-
-
- \Rogue\Monster\
- else
- echo "will not over write lists.doc"
- fi
- if [ `wc -c lists.doc | awk '{printf $1}'` -ne 5861 ]
- then
- echo `wc -c lists.doc | awk '{print "Got " $1 ", Expected " 5861}'`
- fi
- if `test ! -s memory.doc`
- then
- echo "writing memory.doc"
- cat > memory.doc << '\Rogue\Monster\'
-
- MEMORY.DOC
-
- These are general memory handling routines which will perform operations
- as quickly as possible. They are super-optimized to use long word and
- multiple-register moves whenever possible.
-
- BZero BZero
-
- (void) = BZero(buf, bytes)
- APTR buf;
- long bytes;
-
- Zero out an area of memory. That was simple! This is simply a special
- case of BSet()
-
- BSet BSet
-
- (void) = BSet(buf, bytes, value)
- APTR buf;
- long bytes;
- long value; (only lower 8 bits used)
-
- Jam a byte value into an area of memory.
-
-
- BMov BMov
-
- (void) = BMov(src, dest, bytes)
- APTR src, dest;
- long bytes;
-
- Move a block of memory from the source to the destination. An
- ascending or decending copy is used depending on how the source and
- destination overlap, if at all. Both are optimized to use multiple-
- register moves when possible, longword moves, or byte moves if the
- two blocks are hopelessly out of alignment.
-
- BCmp BCmp
-
- BOOL = BCmp(src, dest, bytes)
- APTR src, dest;
- long bytes;
-
- Compare two blocks of memory. (1) is returned on success, (0) on
- failure. Currently, this routine is not optimized at all.
-
-
- \Rogue\Monster\
- else
- echo "will not over write memory.doc"
- fi
- if [ `wc -c memory.doc | awk '{printf $1}'` -ne 1234 ]
- then
- echo `wc -c memory.doc | awk '{print "Got " $1 ", Expected " 1234}'`
- fi
- if `test ! -s misc.doc`
- then
- echo "writing misc.doc"
- cat > misc.doc << '\Rogue\Monster\'
-
- MISC.DOC
-
- These are miscellanious useful routines for your enjoyment.
-
-
- WildCmp WildCmp
-
- CBOOL = WildCmp(wildcard, filename)
- char *wildcard;
- char *filename;
-
- The wildcard characters supported are * and ?. The wildcard is
- compared against the filename and (1) returned on success, (0) on
- failure.
-
-
- WaitMsg WaitMsg
-
- msg = WaitMsg(msg)
- EXECMSG *msg;
-
- This routines Waits for a message to be returned just like WaitIO()
- waits for an io request to complete. The message is REMOVED from the
- reply port after it has returned.
-
- the message must have a valid mn_ReplyPort() and must have been queued
- with PutMsg(), which sets the ln_Type to NT_MESSAGE, and replied with
- ReplyMsg(), which sets the ln_Type to NT_REPLYMSG.
-
-
- CheckMsg CheckMsg
-
- msg/NULL = CheckMsg(msg)
- EXECMSG *msg;
-
- This routine checks to see if the message has been returned. The
- same restrictions apply as for WaitMsg(). the message is NOT removed.
- The message is returned if it has been returned (not removed), or
- NULL otherwise.
-
-
- CheckPort CheckPort
-
- msg/NULL = CheckPort(port)
- EXECMSG *msg;
- PORT *port;
-
- This routine works like WaitPort(), but (1) does not block, and
- (2) does not remove the message. If the port is not empty the first
- message is returned (not removed), else NULL is returned if the port
- is empty.
-
-
- LockAddr LockAddr
-
- (void) LockAddr(&lock)
- long lock[2];
-
- The lock structure (8 bytes) MUST initially be 0. This routine obtains
- an exclusive lock on the structure and blocks until that lock can be
- obtained. The structure must be word-aligned.
-
- Unless it is forced to block, this subroutine is extremely fast. This
- routine does not allocate any signals, but uses the reserved EXEC
- semaphore signal.
-
-
- LockAddrB LockAddrB
-
- (void) LockAddr(bitno, &lock)
- long bitno;
- long lock[2];
-
- The lock structure actually supports up to 8 independant exclusive
- locks. LockAddr() is a special case which uses bit # 0. This call
- works as in LockAddr() but you may specify the bit you wish to lock
- (0 to 7). If you specify 0, this call is equivalent to LockAddr().
-
-
- UnLockAddr UnLockAddr
-
- (void) UnLockAddr(&lock)
- long lock[2];
-
- Remove an exclusive lock you had previously obtained. If other tasks
- are waiting for this lock, ALL are awakened even though only one will
- get the lock next. This ensures that the highest priority task will
- get the lock next.
-
- This routine is extremely fast if nobody else is waiting for the lock,
- else it has to Signal() them. You MUST have previously obtained the
- lock.
-
-
- UnLockAddrB UnLockAddrB
-
- (void) UnLockAddrB(bitno, &lock)
- long bitno;
- long lock[2];
-
- Again, this routine works the same as UnLockAddr() with the exception
- that you may specify one of the 8 bits to unlock (0 to 7).
-
-
- DoSyncMsg DoSyncMsg
-
- (void) DoSyncMsg(port, msg)
- PORT *port;
- EXECMSG *msg;
-
- This routine PutMsg()s a message and waits for it to be returned. This
- routine creates its own reply port on the stack and stuffs it into
- mn_ReplyPort for you. Thus, virtually no setup is required to use
- this routine.
-
-
- FindName2 FindName2
-
- node/NULL = FindName2(list, name)
-
- This routine is identical to the EXEC FindName() call with the exception
- that it ignores nodes whos ln_Name fields are NULL. ln_Name fields in
- the list nodes must contain either NULL or a valid string pointer.
-
-
- GetTaskData GetTaskData
-
- ptr = GetTaskData(name, bytes)
- APTR ptr;
- char *name;
- long bytes;
-
- This routine retrieves/allocates task-private named storage. For a
- specific name, the first GetTaskData() call will allocate the specified
- # of bytes and zero them. Space to hold the name itself is also
- allocated (i.e. you can use a temporary buffer to hold 'name' when you
- make this call). Future calls return the pointer to the already
- allocated storage without modifying it.
-
- The storage is automatically freed if the TASK is removed... note that
- the task is not normally removed when a C program exits back into a
- CLI enviroment... it uses the CLI's task to run the program. The
- task's memory list is used to implement this function.
-
-
- FreeTaskData FreeTaskData
-
- (void) FreeTaskData(name)
- char *name;
-
- If the task-private name exists, the storage associated with it is
- freed. This works with memlist entries allocated with GetTaskData()
- or by the user, assuming the ln_Name field points to a valid string.
-
- (note: FreeEntry() is used after the associated MemList structure is
- unlinked frlom the list. ln_Name is not specifically freed but the
- way GetTaskData() works, the second entry is actually the storage
- associated with the ln_Name)
-
-
- \Rogue\Monster\
- else
- echo "will not over write misc.doc"
- fi
- if [ `wc -c misc.doc | awk '{printf $1}'` -ne 4956 ]
- then
- echo `wc -c misc.doc | awk '{print "Got " $1 ", Expected " 4956}'`
- fi
- if `test ! -s qints.doc`
- then
- echo "writing qints.doc"
- cat > qints.doc << '\Rogue\Monster\'
-
- QINTS.DOC
-
- I call them Q-Interrupts to tell them apart from other types of
- interrupts that exist on the Amiga. QInts provide a general purpose
- priority enhanced local task-interrupt system based on exceptions.
-
- Essentially, one can associate a Q interrupt with any set of EXEC
- signals. When an associated signal comes in, a Q interrupt occurs. The
- interrupt is taken immediately if the current task Q-priority is lower
- than the Q-priority of the interrupt, else it is queued until the
- priority becomes lower.
-
- When a Q-interrupt is taken, the task's Q-priority is raised to that
- of the Q-interrupt while the interrupt is being processed. Additionaly,
- the application software may set the task's Q-priority at any time,
- usually to prevent interrupts from occuring in critical sections.
-
- OpenQInts OpenQInts
-
- handle = OpenQInts()
- long handle;
-
- This routine initializes a handle for the Q interrupt system. All
- 32 EXEC signals may be controlled through this one handle. NULL is
- returned on error, else a non-zero handle is returned.
-
- CloseQInts CloseQInts
-
- (void) = CloseQInts(handle)
- long handle;
-
- This routine shuts down the handle, including the removal of any
- active Q Interrupt vectors.
-
- SetQPri SetQPri
-
- (void) = SetQPri(handle, pri)
- long handle;
- long pri;
-
- This routine sets the current Q-interrupt priority for the task...
- actually all interrupts associated with the handle but this is
- usually all the interrupts period.
-
- Any Q-interrupts with higher priority can occur, while interrupts
- with lower or equal priority will be queued until you SetQPri() to
- a lower value.
-
- 'pri' has a range -127 to 127
-
- SetQVector SetQVector
-
- oldvec = SetQvector(handle, vector, signo, arg, pri)
- void (*oldvec)();
- void (*vector)();
- long handle;
- long signo;
- long arg;
- long pri;
-
- This routine applied or removes or changes the priority of a
- Q interrupt. If vector is NULL, the interrupt is removed for the
- specified signo. If vector is not NULL the interrupt is set for
- the specified signo, replacing any previous interrupt vector and
- priority that existed.
-
- The interrupt has a priority of 'pri', (-127 to 127).
-
- The vector may be a C routine. The OpenQInts() routine saved A4/A5
- and these registers are automatically re-loaded before the vector
- is called to support the small-data model. Additionaly, D2 and D3
- Parameters are also scratch to support Aztec C. Both Aztec and Lattice
- C are thus supported. Parameters to the service routine are passed on
- the stack:
-
- (*vector)(arg)
-
- Specifically, the argument you gave SetQVector().
-
- NOTE: SetQVector() may be called from a Q-interrupt.
-
-
- \Rogue\Monster\
- else
- echo "will not over write qints.doc"
- fi
- if [ `wc -c qints.doc | awk '{printf $1}'` -ne 2789 ]
- then
- echo `wc -c qints.doc | awk '{print "Got " $1 ", Expected " 2789}'`
- fi
- if `test ! -s res.doc`
- then
- echo "writing res.doc"
- cat > res.doc << '\Rogue\Monster\'
-
-
- RESOURCE.DOC
-
- AMIGA RESOURCES AS IMPLEMENTED BY DRES.LIBRARY
-
- The first order of business is to avoid some confusion. The Amiga
- already has resources .... EXEC resources, which are used mainly to
- arbitrate low level hardware. The resources I am talking about is an
- object oriented system and has nothing to do with EXEC resources. All
- references to 'resources' in this document refer to this object
- oriented system.
-
- What is a resources? A resource is a means of accessing one or more
- objects through a generalized interface with as much flexibility as
- possible. A specific object in this system has certain capabilities
- and is referenced by a pointer to something. For instance, an
- intuition Window could be a resource. Each and every resource in the
- system may be flagged as follows (any combination of flags):
-
- SHARABLE - Multiple references to the resource are allowed. If not
- sharable, duplication of a resource results in two
- distinct resources with different data areas rather
- than two pointers to a shared data area.
-
- Duplication of non-sharable resources via DupRes()
- results in a copy of that resource's data including any
- changes made to that data. GetRes()ing it results in
- a pristine copy.
-
- Duplication of a shareable resource returns the common
- data area whether you DupRes() it or GetRes() it.
-
- GLOBAL - A global resource can be accessed by any task in the
- system. NOTE: Private resources can still be
- sharable, but only by a DupRes() call or a GetRes()
- call from a task's private resource list.
-
- Also, any resources tagged as GLOBAL in a task's private
- resource list are immediately accessable to other tasks
- via GetRes(). Searching other task's private lists for
- global resources is always done last.
-
- VIRTUAL - A virtual resource is one that has been algorithmically
- generated. Most resources are virtual resources. For
- example, an intuition Window would be a virtual resource.
-
- Non virtual resources are the 'raw' resources on disk.
- For instance, a "_List" resource would be a raw resource
- but when you GetRes(name, "List") note that obviously
- some conversion code is required to go from "_List" to
- "List", in this case the code initializes the list
- pointers.
-
- Most of the time, the existance of one or more
- algorithms (subroutines) to generate a resource is
- completely transparent to the routine requesting the
- resource. Using the above example, the task requesting
- the resource simply asks for a "List" and is oblivious
- to what actually must be performed to give him that
- List.
-
- SWAPABLE - While not being referenced (all references fall to 0),
- rather than delete the resource, it should be swapped to
- disk (read: any filesystem device) and then swapped
- back in when accessed. This does not mean a resource
- is automatically swapped when references fall to 0,
- just that it *might* be swapped.
-
- This only applies to SHARABLE resources, as you cannot
- DupRes() a non-shared resource when the references fall
- to 0 (nothing to dup), and GetRes() returns a pristine
- copy.
-
- SHARABLE resources on the otherhand are assumed to be
- of a more permanent nature. As in the LOCKED flag
- below, this flag guarentees the resource will not become
- pristine on the next reference after previous usage.
-
- LOCKED - While not being referenced, rather than delete or swap
- the resource, it should stay in memory. This only
- applies to SHARABLE resources.
-
-
- RESOURCE NAMES AND ALGORITHMIC GENERATION
-
- The identification of a resource consists of two parts. (1) The name
- of the resource, and (2) the structure of the resource. The name of
- the resource is arbitrary while the structure of the resource is some
- agreed upon standard. The two parts are stuck together with an
- intervening period like so:
-
- CHArlIE.Window
-
- For the above example, we have a resource named 'CHArlIE' of structure
- 'Window'... an intuition window pointer would be the result of
- accessing this particular resource. However, it is not possible to
- store a Window structure on disk verbatim since there are lots of
- pointers and other dependancies with intuition. On disk, the resource
- might actually be:
-
- CHArlIE.NewWindow
-
- But we want a Window structure... if the program requests
- CHArlIE.Window there must be some means of algorithmically translating
- a NewWindow to a Window. These algorithms are provided by yet a
- third resource named:
-
- NewWindow.Window.CODE
-
- The name is 'NewWindow.Window' and the type is 'CODE'. This resource
- is a procedure which translates a NewWindow to a Window by calling
- OpenWindow(). The translation procedure is recursive, thus allowing
- any manner of 'patching' for reasons given above, for maintaining
- compatibility with older structures, and for convenience.
-
- Finally, a resource is owned by a specific task. One can pass
- resources around but it must be done with cooperation from the
- library.
-
- CODE resources are discussed later on. Now that you have an idea how
- resources work, we shall discuss the library calls currently available:
-
-
-
- RESOURCE LIBRARY CALLS
-
- Beginning with the easiest of the calls and ending with the more
- difficult. NOTE: Resource names are limited to 31 characters,
- Resource types are limited to 31 characters.
-
- resptr= GetRes(resnametype) char *resnametype;
-
- This function retrieves the requested resource, doing any
- translations required to get the resource into the requested
- type. NULL is returned if the resource could not be found
- or could not be translated to the requested type.
-
- In-Memory private resources are searched first, then the private
- resource files for the task, then In-Memory system resources, then
- the global resource files for the system. Openning an already-open
- resource causes one of two actions depending on whether the resource
- is shared or not. If shared, the reference count is simply
- incremented, otherwise a private copy of the resource is made.
-
- Example: Win = GetRes("Charlie.Window");
-
- resptr2 = DupRes(resptr1) APTR resptr1, resptr2;
-
- This call duplicates a resource. If the resource is shared
- resptr2 will be the same as resptr1 and the reference count will
- be bumped. Otherwise, a new resource data area is allocated and
- the old copied to the new.
-
- Things like fixing pointers and such within a resource that is
- physically duplicated are handled by the interface code (since
- raw resources do not contain pointers, only VIRTUAL resources
- will contain pointers and all VIRTUAL resources have some
- interface code).
-
- error = FreeRes(resptr)
-
- Free a resource that you retrieved via GetRes(). Only the task
- that owns the resource may free it (though several tasks may own
- a resource through duplication and ownership changes). 1 is
- returned on success, 0 on error.
-
- That is, if task #1 GetRes()'s the resource and duplicates it once,
- then task #2 duplicates it once, task #1 must call FreeRes() twice
- and task #2 must call FreeRes() once. Ownership is strictly
- tracked.
-
- numres= FreeAllRes(task)
-
- Free all resources associated with the specified task (NULL for
- self).
-
- error = ChownRes(resptr, fromtask, totask)
-
- Change ownership of a resource from the source task to the
- destination task. The resource must be owned by the source
- task or an error will occur (0 return value). 1 is returned
- on success. NULL may be specified for either or both tasks
- and means the calling task.
-
- handle= UnLinkAllRes(task)
-
- Unlink all resources associated with the specified task (NULL
- for self) and return a handle representing those resources.
-
- This is useful for shells and such to keep their resources from
- getting removed by commands they run. Combined with the NUNLINK
- flag one can pass resources to a Command and keep the rest out of
- reach.
-
- (void) ReLinkAllRes(handle, task)
-
- Link all the resources represented by the handle to the specified
- task (NULL for self).
-
- oldfl = SetResFlags(resptr, newflags, flagsmask)
-
- Modify the flags associated with a resource. NOTE: If multiple
- references to a shared resource exist, all are modified. Some
- modifications may be disallowed by the system. This call is
- normally used to modify the LOCKED and SWAPABLE flags (note that
- the SWAPABLE flag can be changed back and forth only for resource
- which support it).
-
- error = AddRes(resnametype, flags, ptr, ctlcode);
- char *resnametype;
- long flags;
- APTR ptr;
- long (*ctlcode)();
-
- Add a resource to the system. The resource is placed either in
- the task's privately accessable in-memory resource list or
- in the system global accessable in-memory resource list depending
- on the specified flags. One may now GetRes() the resource.
-
- ONLY VIRTUAL RESOURCES MAY BE ADDED IN THIS WAY. The VIRTUAL
- and LOCKED flags are automatically set.
-
- If flags specifies a VIRTUAL resource
-
- error = RemRes(resname)
-
- Remove the specified resource. An error will occur and the resource
- will not be removed (1) if it does not exist in memory, or (2) it
- is currently being referenced. (Note: the resource is removed even
- if it is swapped or locked).
-
- error = GetResInfo(resname, &flags, &bytes)
-
- Get information on a resource. Information may not exist for a
- resource if it is not currently in memory and would have to be
- translated to get to the right type.
-
- error = GetResList(wildcard, from, &av, &ac);
-
- from: mask, bit 0 search private list
- 1 search system list
- 2 <not used>
- 3 search in-memory private list
- 4 search in-memory global list
-
- Return an ARGC/ARGV list of resource names. Note that some names
- might be duplicated if searching multiple lists. Restricting the
- search to in-memory lists give resources which are already in
- memory (but might be swapped out or removed at any time for those
- with no references)
-
- RESOURCE FILES
-
- error = GetFileList(wildcard, from, &av, &ac);
-
- from: mask, bit 0 search private list
- 1 search system list
- 2 search swap list
-
- Return an ARGC/ARGV list of the files which match the specified
- wildcard from the private list, system list, or system swap dir
- list (in which case you get directory names). This list has been
- allocated, and can be freed as follows:
-
- Loop through all entries for (i = 0; i < ac; ++i)
- FreeMem(av[i], strlen(av[i])+1);
- Free the array itself: FreeMem(av, sizeof(char *) * (ac+1));
-
- num = AddPrivResFile(filename, pri)
-
- Add a file name to the list of resource files for this task. These
- are scanned before global files when a resource is requested. All
- files in the list are write protected (i.e. a shared lock is kept
- for each file). Thus, such files cannot be updated until removed
- from the list.
-
- Can also be used to modify the priority of an existing file
-
- num = RemPrivResFiles(wildcard)
-
- Remove zero or more file names from the list of resource files for
- this task. A wildcard pattern (* and ?) is accepted.
-
- Note for command processors: commands you run might execute
- this command for *.
-
- num = AddGlobResFile(filename, pri)
-
- Same as AddPrivResFile() but applies to the system list, which is
- searched last and by any requesting task. Wildcard file names are
- NOT accepted. The file need not exist at this time, and references
- to unmounted volumes are allowed.
-
- Can also be used to modify the priority of an existing entry
-
- num = RemGlobResFiles(wildcard)
-
- Remove zero or more resource files from the global list. Again,
- a wildcard filename is accepted.
-
- num = AddResSwapDir(dirname, pri, maxkbytes) char *dirname;
- char pri;
- long maxkbytes
-
- Add a directory to the list of directories the resource system
- can swap to. The maximum number of KBytes of material allowed
- in the directory should be specified. You can also use this
- call to modify the priority and maxkbytes for an entry.
-
- The highest priority directories are used before lower priority
- directories. Not all directories need be mounted, but if a swapin
- occurs from an unmounted directory a requester will appear.
-
- A lock is kept on each specified directory.
-
- num = RemResSwapDirs(wildcard)
-
- Remove directories associated with the resource swap areas.
-
-
- RESOURCE FILE IFF FORMAT
-
-
- \Rogue\Monster\
- else
- echo "will not over write res.doc"
- fi
- if [ `wc -c res.doc | awk '{printf $1}'` -ne 12714 ]
- then
- echo `wc -c res.doc | awk '{print "Got " $1 ", Expected " 12714}'`
- fi
- if `test ! -s runlib.doc`
- then
- echo "writing runlib.doc"
- cat > runlib.doc << '\Rogue\Monster\'
-
- DRES.LIBRARY
-
- OVERVIEW OF FUNCTIONS
-
- This document is meant to give a simple overview of library functions,
- not to provide complete explanations. Please refer to the separate
- document files for various command groups for more detailed information.
-
- * All function arguments are 32 bits unless otherwise specified
-
- * Any Address register may be used to hold the library base pointer
- when calling library routines from assembly.
-
-
- IPC
-
- ipcport = OpenIPC(name, 0)
- (void) = CloseIPC(ipcport)
- ipcmsg = SendIPC(name, buf, len, flags)
- ipcmsg = SendIPC2(name, ipcmsg)
- (void) = ReplyIPC(msg, buf, len, flags)
- (void) = FreeIPC(msg)
- (void) = DoIPC2(name, msg, handler, ipcport)
-
- argc = ParseCmd(str, &argv, varget, varfree, &error, NULL)
- FreeParseCmd(argv)
-
- QINTS
-
- handle = OpenQInts()
- (void) = CloseQInts(handle)
- (void) = SetQPri(handle, pri)
- oldvect = SetQVector(handle, vector, signo, arg, pri)
-
- MISC
-
- BOOL = WildCmp(wildcard, filename)
- msg = WaitMsg(msg)
- msg/NULL= CheckMsg(msg)
- msg/NULL= CheckPort(port)
- (void) = LockAddr(&varlock) (long varlock[2] = { 0,0 })
- (void) = LockAddrB(bitno, &varlock)
- (void) = UnLockAddr(&varlock)
- (void) = UnLockAddrB(bitno, &varlock)
- (void) = DoSyncMsg(port, msg) (do not setup reply port for message)
- node/NULL= FindName2(list, name) (ignores NULL ln_Name fields)
- ptr = GetTaskData(name, bytes)
- (void) = FreeTaskData(name)
-
- LISTS
-
- node = GetHead(list)
- node = GetTail(list)
-
- node = GetSucc(list/node)
- node = GetPred(node)
-
- sptr = GetHeadOff(list, offset)
- sptr = GetTailOff(list, offset)
- sptr = GetSuccOff(sptr, offset)
- sptr = GetPredOff(sptr, offset)
-
- (void) = EnqueueLong(list, start, node, valoff)
- (void) = EnqueueOffLong(list, start, sptr, off, valoff)
-
- rval = SearchFwdNode(node, function, arg)
- rval = SearchRvsNode(node, function, arg)
- rval = SearchFwdList(list, function, arg)
- rval = SearchRvsList(list, function, arg)
- rval = SearchFwdNodeOff(sptr, function, off, arg)
- rval = SearchRvsNodeOff(sptr, function, off, arg)
- rval = SearchFwdListOff(list, function, off, arg)
- rval = SearchRvsListOff(list, function, off, arg)
-
- >> function(sptr:4(sp)orA2, arg:8(sp)orD4)
-
- MEMORY
-
- (void) = BZero(buf, bytes)
- (void) = BSet(buf, bytes, char)
- (void) = BMov(src, dest, bytes)
- BOOL = BCmp(src, dest, bytes) 0=failed, 1=success
-
- TIMEDATE
-
- DOSBOOL = SetFileDate(file, date) 0=failed, -1=success
- char * = DateToS(datestamp, buf, format)
-
- RESOURCES (NOT IMPLEMENTED YET)
-
- \Rogue\Monster\
- else
- echo "will not over write runlib.doc"
- fi
- if [ `wc -c runlib.doc | awk '{printf $1}'` -ne 2799 ]
- then
- echo `wc -c runlib.doc | awk '{print "Got " $1 ", Expected " 2799}'`
- fi
- if `test ! -s timedate.doc`
- then
- echo "writing timedate.doc"
- cat > timedate.doc << '\Rogue\Monster\'
-
-
- TIMEDATE.DOC
-
- Useful routines...
-
- SetFileDate SetFileDate
-
- DOSBOOL = SetFileDate(file, date)
- char *file;
- DATESTAMP *date;
-
- This routine sets the datestamp for a file by implementing the new
- ACTION_SETDATE Dos packet. 0 is returned on failure, non-zero (-1)
- on success.
-
- NOTE: The routine will fail if the file has been locked, shared or
- otherwise.
-
-
- DateToS DateToS
-
- buf = DateToS(date, buf, format)
-
- DATESTAMP *date;
- char *buf;
- char *format;
-
- This routine calculates the ascii time and date from the datestamp and
- jams it into the output buffer (which is returned) according to the
- specified format string. If the format string is NULL, "D M Y h:m:s"
- is used. Essentially, the characters D,M,Y,h,m, and s are replaced by
- their ascii date equivalents (day, month, year, hours, minutes, seconds)
- in the output buffer, with all other characters copied verbatim.
-
-
- \Rogue\Monster\
- else
- echo "will not over write timedate.doc"
- fi
- if [ `wc -c timedate.doc | awk '{printf $1}'` -ne 968 ]
- then
- echo `wc -c timedate.doc | awk '{print "Got " $1 ", Expected " 968}'`
- fi
- echo "Finished archive 1 of 1"
- # if you want to concatenate archives, remove anything after this line
- exit
- --
- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
- Have five nice days.
-